package com.chen.blue.service.system.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.chen.blue.annotation.permission.DataPermission;
import com.chen.blue.container.PermissionFlag;
import com.chen.blue.converter.system.DeptConverter;
import com.chen.blue.converter.system.MenuConverter;
import com.chen.blue.converter.system.RoleConverter;
import com.chen.blue.domain.delete.system.DeptDelete;
import com.chen.blue.domain.dto.system.DeptDto;
import com.chen.blue.domain.dto.system.update.DeptDtoEdit;
import com.chen.blue.domain.model.system.DeptModel;
import com.chen.blue.domain.model.system.RoleModel;
import com.chen.blue.domain.query.system.DeptQuery;
import com.chen.blue.domain.vo.system.DeptVo;
import com.chen.blue.domain.vo.system.MenuVo;
import com.chen.blue.domain.vo.system.RoleVo;
import com.chen.blue.exception.e.DtoNullException;
import com.chen.blue.mapper.system.DeptMapper;
import com.chen.blue.result.DataResult;
import com.chen.blue.service.candidate.CandidateInfoService;
import com.chen.blue.service.system.IDeptService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chen.blue.utils.PageInfoUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 部门表 服务实现类
 * </p>
 *
 * @author CLT
 * @since 2024-04-29
 */
@Service("iDeptService")
public class IDeptServiceImpl extends ServiceImpl<DeptMapper, DeptModel> implements IDeptService {

    @Override
    public boolean addDept(DeptDto deptDto) throws DtoNullException {

        if (Objects.isNull(deptDto)) {
            throw new DtoNullException("参数为空");
        }

        DeptModel deptModel = DeptConverter.dtoToModel(deptDto);

        CandidateInfoService.setCreator(deptModel);

        return super.save(deptModel);

    }

    @Override
    public boolean deleteDept(DeptDelete deptDelete) throws DtoNullException {

        if (Objects.isNull(deptDelete)) {
            throw new DtoNullException("参数为空");
        }

        Map<String, Object> wrap = new HashMap<>();
        if (Objects.nonNull(deptDelete.getId())) {
            wrap.put("id", deptDelete.getId());
        }

        return Objects.nonNull(deptDelete.getIds()) ? super.removeByIds(deptDelete.getIds()) : super.removeByMap(wrap);

    }

    @Override
    public boolean updateDeptById(DeptDtoEdit deptDtoEdit) throws DtoNullException {

        if (Objects.isNull(deptDtoEdit)) {
            throw new DtoNullException("参数为空");
        }

        DeptModel deptModel = DeptConverter.dtoEditToModel(deptDtoEdit);

        CandidateInfoService.setUpdater(deptModel);

        return super.updateById(deptModel);

    }

    @DataPermission
    @Override
    public DataResult<List<DeptVo>> queryDept(DeptQuery deptQuery, boolean isTree) throws DtoNullException {

        if (Objects.isNull(deptQuery)) {
            throw new DtoNullException("查询条件为空");
        }

        LambdaQueryWrapper<DeptModel> wrapper = new LambdaQueryWrapper<>();
        if (Objects.nonNull(deptQuery.getPageNo()) && Objects.nonNull(deptQuery.getPageSize())) {
            PageHelper.startPage(deptQuery.getPageNo(), deptQuery.getPageSize());
        }
        wrapper.orderByDesc(DeptModel::getCreateTime);

        List<DeptModel> deptModelList = super.list(wrapper);
        PageInfo<DeptModel> pageInfo = new PageInfo<>(deptModelList);
        PageHelper.clearPage();

        // 关闭数据权限
        PermissionFlag.set(false);

        /**
         * 统一结果返回
         */
        DataResult<List<DeptVo>> dataResult = new DataResult<>();
        List<DeptVo> deptVoList = DeptConverter.modelToVoList(pageInfo.getList());
        // 返回树形结构
        List<DeptVo> list = DeptConverter.modelToVoList(pageInfo.getList());
        List<DeptVo> menuVoTree = Objects.isNull(list) ? null : list.size() == 1 ? (List<DeptVo>) queryDeptById(list.get(0).getId()).getResult() : getMenuVoTree(0L, null, list);
        // 判断是否返回树形结构
        dataResult.setData(isTree ? menuVoTree : deptVoList);
        PageInfoUtil.setPageInfo(dataResult, pageInfo);

        return dataResult;

    }

    @Override
    public DataResult<List<DeptVo>> queryDeptById(Long id) throws DtoNullException {

        if (Objects.isNull(id)) {
            throw new DtoNullException("ID为空");
        }

        DeptModel deptModel = super.getById(id);
        DataResult<List<DeptVo>> dataResult = new DataResult<>();
        DeptVo deptVo = DeptConverter.modelToVo(deptModel);
        List<DeptVo> menuVoList = getMenuVoTreeById(deptVo != null ? deptVo.getId() : null, DeptConverter.modelToVoList(super.list()));
        dataResult.setData(menuVoList);

        return dataResult;

    }


    /**
     * 返回整体部门的树形结构
     *
     * @param list
     * @return
     */
    protected List<DeptVo> getMenuVoTree(Long parentId, String parentName, List<DeptVo> list) {

        if (Objects.isNull(list) || Objects.isNull(parentId)) {
            return null;
        }

        return list.stream()
                .filter(obj -> obj.getParentId().equals(parentId))
                .map(obj -> {
                    obj.setChildren(setChildrenList(obj.getId(), obj.getName(), list));
                    obj.setParentName(parentName);
                    return obj;
                })
                .collect(Collectors.toList());
    }

    /**
     * 返回指定id的部门及其子部门
     *
     * @param id
     * @param list
     * @return
     */
    protected List<DeptVo> getMenuVoTreeById(Long id, List<DeptVo> list) {

        if (Objects.isNull(list) || Objects.isNull(id)) {
            return null;
        }

        return list.stream()
                .filter(obj -> obj.getId().equals(id))
                .peek(obj -> obj.setChildren(setChildrenList(obj.getId(), obj.getName(), list)))
                .collect(Collectors.toList());
    }


    /**
     * 返回指定id的子部门
     *
     * @param parentId
     * @param list
     * @return
     */
    protected List<DeptVo> setChildrenList(Long parentId, String parentName, List<DeptVo> list) {

        return list.stream().filter(obj -> obj.getParentId().equals(parentId))
                .map(obj -> {
                    obj.setChildren(setChildrenList(obj.getId(), obj.getName(), list));
                    obj.setParentName(parentName);
                    return obj;
                }).collect(Collectors.toList());

    }

}
